package com.lzk.jetpacktest.coroutine

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import com.lzk.jetpacktest.R
import kotlinx.android.synthetic.main.activity_coroutine.*
import kotlinx.coroutines.*
import java.lang.IllegalStateException
import java.util.*
import kotlin.system.measureTimeMillis

class CoroutineActivity : AppCompatActivity() {

    private var mJob: Job? = null

    private val mViewModel: CoroutineViewModel by lazy {
        ViewModelProvider(this).get(CoroutineViewModel::class.java)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_coroutine)

        coroutine_btn.setOnClickListener {
            requestGirlInfo()
        }


        mJob = lifecycleScope.launch {

            delay(1000)
            Log.d("TAG","Job is Completed:${mJob?.isCompleted}")
        }

        async()

        //CoroutineContext是一个Element实例集合
        //由Job、CoroutineDispatcher、CoroutineName、CoroutineExceptionHandler组成
        val coroutineContext = Job() + Dispatchers.Main + CoroutineName("MyCoroutineContext") +CoroutineExceptionHandler { coroutineContext, throwable ->
            throwable.printStackTrace()
            Log.d("TAG","throwable:$throwable")
        }

        //一个Job可以包含多个子Job，
        // 当父Job被取消后，所有的子Job也会被自动取消；
        // 当子Job被取消或者出现异常后父Job也会被取消。
        //这里childJob3出现异常后，childJob1就不会执行了，
        // 因为launch()的协程上下文是自定义的coroutineContext，如果使用launch()的默认上下文（EmptyCoroutineContext）,则childJob3出现异常后childJob1仍会执行。
//        val jobA = lifecycleScope.launch(coroutineContext) {
//
//            val childJob1 = lifecycleScope.launch(coroutineContext) {
//                delay(2000)
//                Log.d("TAG","childJob1")
//            }
//
//            val childJob2 = lifecycleScope.launch(coroutineContext) {
//                delay(500)
//                Log.d("TAG","childJob2")
//            }
//
//            //需要捕获异常，否则会崩溃
//            val childJob3 = lifecycleScope.launch(coroutineContext) {
//                delay(1000)
//                Log.d("TAG","childJob3")
//                throw IllegalStateException()
//            }
//        }

        //MainScope
        //MainScope的job是SupervisorJob，当子Job被取消或出现异常后(需捕获异常，不然会崩溃)，其他job不会取消
        val mainScope = MainScope()+CoroutineExceptionHandler { _, throwable ->
            throwable.printStackTrace()
            Log.d("TAG","throwable:$throwable")
        }
        val jobB = mainScope.launch{

            val childJob1 = mainScope.launch {
                delay(2000)
                Log.d("TAG","childJob1")
            }

            val childJob2 = mainScope.launch {
                delay(500)
                Log.d("TAG","childJob2")
            }

            //需要捕获异常，否则会崩溃
            val childJob3 = mainScope.launch {
                delay(1000)
                Log.d("TAG","childJob3")
                throw IllegalStateException()
            }
        }
    }

    private fun async(){
        val handler = CoroutineExceptionHandler { coroutineContext, throwable ->
            throwable.printStackTrace()
            Log.d("TAG","async throwable:$throwable")
        }
        val scope = MainScope() + handler
        scope.launch {
            val a = async {
                //val response = mViewModel.requestGirlInfo()
                //Log.d("TAG","***async a:$response  ****")
                delay(500)
                Log.d("TAG","***async a****")
                throw IllegalStateException("async a error")
//                "true"
            }
            val b = async {
                delay(1000)
                Log.d("TAG","***async b****")
                "true"
            }

            val c = async {
                Log.d("TAG","***async c****")
                "true"
            }

            val d = async {
                delay(600)
                Log.d("TAG","***async d****")
                "false"
            }
            val list = listOf<Deferred<String>>(a,b,c,d)
            //并发
//            val time1 = measureTimeMillis {
//                a.await()
//                b.await()
//                c.await()
//                d.await()
//            }
//            Log.d("TAG","time1:${time1}")
            //并发
            val time2 = measureTimeMillis {
                list.forEach {
                    val result = it.requestAwait()
                    Log.d("TAG","async result:${result}")
                }
            }
            Log.d("TAG","time2:${time2}")

        }
    }

    private fun requestGirlInfo() {
        lifecycleScope.launchWhenResumed {
            val response = mViewModel.requestGirlInfo()
            if (response.data.isNullOrEmpty()) {
                Toast.makeText(this@CoroutineActivity, "数据获取失败", Toast.LENGTH_SHORT).show()
            } else {
                val random = Random()
                val index = random.nextInt(response.data.size - 1)
                coroutine_tv.text = response.data[index].desc
            }
        }
    }

    private suspend fun <T> Deferred<T>.requestAwait(): String{
        var string = ""
        kotlin.runCatching {
            this.await()
        }.onSuccess {
            string = "success:${it.toString()}"
        }.onFailure {
            string = "async error:${it.toString()}"
        }
        return string
    }

}